/**
 * 
 *   Code contributed by IUP Research Institute
 * 
 *     This file is part of NetworkMon.
 *
 *   NetworkMon is free software; you can redistribute it and/or modify
 *   it under the terms of the GNU General Public License as published by
 *   the Free Software Foundation; version 2 of the License.
 *
 *   NetworkMon is distributed in the hope that it will be useful,
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *   GNU General Public License for more details.
 *
 *   You should have received a copy of the GNU General Public License
 *   along with NetworkMon; if not, write to the Free Software
 *   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 */
package networkbackend;

import java.util.Iterator;

/**
 * 
 * @author fkern
 * @author petersen
 */
public class packetQueue extends Thread {

	private NetworkViewer c;
	private AddressLinkedList addressList;
	public int selectedDevice = -1;

	public int packetCount;
	public int byteCount;
	public String addressFilter;

	protected javax.swing.event.EventListenerList listenerList = new javax.swing.event.EventListenerList();

	/** Creates a new instance of packetQueue */
	public packetQueue(String filterAddress) {

		if (filterAddress != null) {
			addressFilter = filterAddress.substring(0,
					filterAddress.length() - 1);
		} else {

			addressFilter = null;
		}

		addressList = new AddressLinkedList();

		c = new NetworkViewer();

	}

	public String[] Devices() {
		return c.getAllDevices();
	}

	@Override
	public void run() {

		c.addthePacketListener(new PacketListenerHandler(this));

		c.StartGettingPackets(selectedDevice);

	}

	public void stopIt() {

		c.StopGettingPackets();

		c.removethePacketListener(new PacketListenerHandler(this));
	}

	@SuppressWarnings( { "unchecked", "unchecked" })
	public AddressLinkedList GetAddresses() {
		AddressLinkedList retval = new AddressLinkedList();

		synchronized (this) {

			Iterator<Object> iterator = addressList.iterator();
			AddressNode currentNode = null;

			while (iterator.hasNext()) {
				currentNode = (AddressNode) iterator.next();
				retval.add(currentNode);
			}

		}
		return retval;

	}

	private boolean FilterPacket(String filter, String address) {
		boolean retval = false;

		if (filter == null) {
			return true;
		}

		if (filter != null && address != null) {
			if (address.indexOf(filter) >= 0) {
				retval = true;

			}
		}

		return retval;
	}

	// save the packet data to the address list and then to the packet list
	@SuppressWarnings("unchecked")
	public void Save(PacketNode newNode) {

		// if the received packet does not fall into the filter 'range' do not
		// save
		// the newly arrived packet thingie (checking src and dest addresses of
		// course!)
		if (FilterPacket(this.addressFilter, newNode.sourceAddress) == false
				&& FilterPacket(this.addressFilter, newNode.destinationAddress) == false) {
			return;
		}

		AddressNode newAddressNode;

		long currentTime = java.lang.System.currentTimeMillis();

		newNode.timeStamp = new java.util.Date(currentTime);

		// if the filter matches the source address, make a node for the source
		// address
		// if the filter matches the destination address, make a node for the
		// destination address
		if (FilterPacket(this.addressFilter, newNode.sourceAddress) == true) {
			newAddressNode = new AddressNode(newNode.sourceAddress,
					newNode.sourcePort);
			newNode.isSent = true;
		} else {
			newAddressNode = new AddressNode(newNode.destinationAddress,
					newNode.destinationPort);
			newNode.isSent = false;
		}

		AddressNode foundAddressNode = null;

		// critical section the list accessing

		synchronized (this) {

			packetCount += 1;
			byteCount += newNode.length;

			foundAddressNode = Find(newAddressNode.address);

			// is the address node in the list already?
			if (foundAddressNode == null) {

				// add the new address node to the list
				addressList.addLast(newAddressNode);

				// save the packet data to the new address node
				newAddressNode.Save(newNode);

				// fire the added event
				fireTheAddEvent(newAddressNode, newNode);
			} else {

				// save the node data to the list
				foundAddressNode.Save(newNode);

				// fire the updated event
				fireTheUpdateEvent(foundAddressNode, newNode);
			}

		}
		return;
	}

	// searches the list to find a match, returns the matching node or NULL if
	// not found
	public AddressNode Find(String label) {
		AddressNode retval = null;
		int index = -1;

		// is the label already in the list?
		index = addressList.indexOf(label);

		// if it is get the index and return the node
		if (index >= 0) {

			retval = (AddressNode) addressList.get(index);

		}

		return retval;
	}

	public AddressNode get(int Index) {
		AddressNode retval = null;

		retval = (AddressNode) addressList.get(Index);

		return retval;
	}

	// <editor-fold defaultstate="collapsed" desc=" Event Stuffs ">

	public void addtheComputerListener(PacketAddedEvent listener) {
		listenerList.add(PacketAddedEvent.class, listener);
	}

	public void removetheComputerListener(PacketAddedEvent listener) {
		listenerList.remove(PacketAddedEvent.class, listener);
	}

	void fireTheAddEvent(AddressNode node, PacketNode packet) {
		Object[] listeners = listenerList.getListenerList();
		// Each listener occupies two elements - the first is the listener class
		// and the second is the listener instance
		for (int i = 0; i < listeners.length; i += 2) {
			if (listeners[i] == PacketAddedEvent.class) {
				((PacketAddedEvent) listeners[i + 1]).ComputerAdded(node,
						packet);
			}
		}
	}

	void fireTheUpdateEvent(AddressNode node, PacketNode packet) {
		Object[] listeners = listenerList.getListenerList();
		// Each listener occupies two elements - the first is the listener class
		// and the second is the listener instance
		for (int i = 0; i < listeners.length; i += 2) {
			if (listeners[i] == PacketAddedEvent.class) {
				((PacketAddedEvent) listeners[i + 1]).ComputerUpdated(node,
						packet);
			}
		}
	}
	// </editor-fold>
}
